# -*- coding: utf-8 -*-
# 趋势回调后延续的量化策略实现
# 趋势识别：确认市场处于上升趋势中
# 回调判定：识别上升趋势中的健康回调
# 延续确认：价格止跌并恢复上升动能
# 进场信号：满足以上所有条件时触发做多
from utils.config import *
from utils.utils import *
import pandas as pd
import utils.MyTT as Mytt
import numpy as np;
# import logging
from utils.log import Loggers
from utils.pushService import PushService

logger = Loggers('MovingAverage')
# logger.clear()

pushSer = PushService('趋势回调后延续策略')



def identify_uptrend(df, ma_window=50, atr_multiplier=3):
    """
    识别上升趋势条件
    参数:
        ma_window: 均线窗口(默认50日)
        atr_multiplier: 趋势通道宽度乘数
    返回:
        添加趋势识别列的DataFrame
    """
    df = df.copy()
    
    # 计算均线
    df['ma'] = df['close'].rolling(ma_window).mean()
    
    # 计算ATR(真实波幅)
    df['tr'] = np.maximum(
        df['high'] - df['low'],
        np.maximum(
            abs(df['high'] - df['close'].shift(1)),
            abs(df['low'] - df['close'].shift(1))
        )
    )
    df['atr'] = df['tr'].rolling(ma_window).mean()
    
    # 上升趋势条件(价格在均线之上且距离不超过3倍ATR)
    df['uptrend'] = (df['close'] > df['ma']) & \
                   (df['close'] <= (df['ma'] + atr_multiplier * df['atr']))
    
    return df


def identify_pullback(df, retracement_threshold=0.382, min_candles=3):
    """
    识别健康回调
    参数:
        retracement_threshold: 回撤比例阈值(默认38.2%)
        min_candles: 最小回调K线数量
    返回:
        添加回调识别列的DataFrame
    """
    df = df.copy()
    
    # 计算最近波段高点和低点
    df['recent_high'] = df['high'].rolling(min_candles*2).max()
    df['recent_low'] = df['low'].rolling(min_candles*2).min()
    
    # 计算回撤幅度
    df['retracement'] = (df['recent_high'] - df['close']) / \
                       (df['recent_high'] - df['recent_low'] + 1e-6)  # 避免除零
    
    # 回调条件
    df['pullback'] = (df['retracement'] >= retracement_threshold) & \
                    (df['retracement'] <= 0.618) & \
                    (df['close'] < df['close'].shift(min_candles-1))
    
    return df


def confirm_continuation(df, confirmation_candles=2):
    """
    确认趋势延续
    参数:
        confirmation_candles: 确认K线数量
    返回:
        添加延续确认列的DataFrame
    """
    df = df.copy()
    
    # 止跌条件(连续n根K线低点上移)
    df['higher_lows'] = df['low'] > df['low'].rolling(confirmation_candles).min().shift(1)
    
    # 动能恢复条件(收盘价突破回调阶段高点)
    df['recent_pullback_high'] = df['high'].rolling(confirmation_candles*3).max()
    df['momentum_resume'] = df['close'] > df['recent_pullback_high']
    
    # 成交量确认(近期成交量放大)
    df['volume_ma'] = df['volume'].rolling(20).mean()
    df['volume_spike'] = df['volume'] > df['volume_ma'] * 1.5
    
    # 综合延续条件
    df['continuation'] = df['higher_lows'] & df['momentum_resume'] & df['volume_spike']
    
    return df


def trend_pullback_strategy(df):
    """
    趋势回调延续策略主函数
    """
    df = identify_uptrend(df)
    df = identify_pullback(df)
    df = confirm_continuation(df)
    
    # 生成做多信号(所有条件满足且前一日无信号)
    df['signal'] = 0
    df.loc[df['uptrend'] & df['pullback'] & df['continuation'], 'signal'] = 1
    
    # 信号去重(连续多日满足条件只取第一次)
    df['signal'] = df['signal'].diff().clip(lower=0)
    
    return df


def multi_timeframe_confirmation(df, higher_tf_data):
    """
    更高时间框架趋势确认
    """
    # 合并高时间框架数据
    merged = pd.merge_asof(
        df, higher_tf_data[['ma', 'uptrend']], 
        left_index=True, right_index=True,
        suffixes=('', '_higher')
    )
    
    # 只有当高时间框架也是上升趋势时才确认信号
    df['signal'] = df['signal'] & merged['uptrend_higher']
    
    return df


def calculate_rr_ratio(df):
    """
    计算动态风险回报比
    """
    # 止损位设为回调最低点
    df['stop_loss'] = df['low'].rolling(10).min()
    
    # 止盈位设为前高+1倍ATR
    df['take_profit'] = df['recent_high'] + df['atr']
    
    # 计算风险回报比
    df['rr_ratio'] = (df['take_profit'] - df['close']) / (df['close'] - df['stop_loss'])
    
    # 只有当RR比>=2时才确认信号
    df['signal'] = df['signal'].astype(bool) & (df['rr_ratio'] >= 2)
    
    return df


def volatility_filter(df, min_atr=0.01):
    """
    波动率过滤(避免在低波动市场交易)
    """
    # 计算ATR相对于价格的百分比
    df['atr_pct'] = df['atr'] / df['close']
    
    # 只有当波动率足够时才交易
    df['signal'] = df['signal'] & (df['atr_pct'] >= min_atr)
    
    return df


def enhanced_trend_pullback_strategy(df, higher_tf_data=None):
    """
    强化版趋势回调延续策略
    """
    # 基础信号
    df = trend_pullback_strategy(df)
    
    # 强化条件
    # df = calculate_rr_ratio(df)
    # df = volatility_filter(df)
    
    if higher_tf_data is not None:
        df = multi_timeframe_confirmation(df, higher_tf_data)
    
    # 添加信号强度指标
    # df['signal_strength'] = df['rr_ratio'] * df['atr_pct'] * df['volume']/df['volume_ma']
    
    return df



# 循环处理
for instId in config_movingAverage_instId:
        # 读取300条最新的数据
    df = loadCsvData(instId,'15m')
    df['signal'] = 0
    df = enhanced_trend_pullback_strategy(df)

    df_signal = df[df['signal']!=0]
    print(df_signal.tail(10))
    # 简要的输出策略表现
    # getShenglvShow(df)

    exit()